package com.education.platform.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.education.platform.common.ResultCode;
import com.education.platform.entity.Conversation;
import com.education.platform.entity.Message;
import com.education.platform.entity.User;
import com.education.platform.exception.BusinessException;
import com.education.platform.mapper.ConversationMapper;
import com.education.platform.mapper.MessageMapper;
import com.education.platform.mapper.UserMapper;
import com.education.platform.service.MessageService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

/**
 * 消息服务实现类
 *
 * @author education-platform
 * @since 2024-10-07
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class MessageServiceImpl implements MessageService {

    private final MessageMapper messageMapper;
    private final ConversationMapper conversationMapper;
    private final UserMapper userMapper;

    @Override
    @Transactional
    public Long sendMessage(Long fromUserId, Long toUserId, String content, String contentType, String extraData) {
        // 验证用户是否存在
        User fromUser = userMapper.selectById(fromUserId);
        User toUser = userMapper.selectById(toUserId);
        if (fromUser == null || toUser == null) {
            throw new BusinessException(ResultCode.NOT_FOUND);
        }

        // 获取或创建会话
        String conversationId = getOrCreateConversation(fromUserId, toUserId);

        // 创建消息
        Message message = new Message();
        message.setFromUserId(fromUserId);
        message.setToUserId(toUserId);
        message.setConversationId(conversationId);
        message.setType(Message.Type.CHAT.name());
        message.setContentType(contentType != null ? contentType : Message.ContentType.TEXT.name());
        message.setContent(content);
        message.setExtraData(extraData);
        message.setStatus(Message.Status.UNREAD.name());

        messageMapper.insert(message);

        // 更新会话最后消息信息
        conversationMapper.updateLastMessage(conversationId, message.getId(), content);

        log.info("发送消息成功, ID: {}, 发送者: {}, 接收者: {}", message.getId(), fromUserId, toUserId);
        return message.getId();
    }

    @Override
    @Transactional
    public Long sendSystemMessage(Long toUserId, String title, String content, String extraData) {
        // 验证用户是否存在
        User toUser = userMapper.selectById(toUserId);
        if (toUser == null) {
            throw new BusinessException(ResultCode.NOT_FOUND);
        }

        // 创建系统消息
        Message message = new Message();
        message.setFromUserId(null); // 系统消息
        message.setToUserId(toUserId);
        message.setType(Message.Type.SYSTEM.name());
        message.setContentType(Message.ContentType.TEXT.name());
        message.setTitle(title);
        message.setContent(content);
        message.setExtraData(extraData);
        message.setStatus(Message.Status.UNREAD.name());

        messageMapper.insert(message);

        log.info("发送系统消息成功, ID: {}, 接收者: {}", message.getId(), toUserId);
        return message.getId();
    }

    @Override
    @Transactional
    public void batchSendSystemMessage(List<Long> userIds, String title, String content, String extraData) {
        for (Long userId : userIds) {
            try {
                sendSystemMessage(userId, title, content, extraData);
            } catch (Exception e) {
                log.error("批量发送系统消息失败, 用户ID: {}", userId, e);
            }
        }
        log.info("批量发送系统消息完成, 用户数量: {}", userIds.size());
    }

    @Override
    @Transactional
    public void broadcastMessage(String title, String content, String extraData) {
        // 获取所有用户ID
        List<User> users = userMapper.selectList(null);
        List<Long> userIds = users.stream().map(User::getId).toList();
        
        batchSendSystemMessage(userIds, title, content, extraData);
        log.info("广播消息完成, 用户数量: {}", userIds.size());
    }

    @Override
    @Transactional
    public void markMessageAsRead(Long messageId, Long userId) {
        Message message = getMessageById(messageId);
        
        // 检查权限：只有接收者可以标记为已读
        if (!message.getToUserId().equals(userId)) {
            throw new BusinessException(ResultCode.FORBIDDEN);
        }

        if (Message.Status.UNREAD.name().equals(message.getStatus())) {
            message.setStatus(Message.Status.READ.name());
            message.setReadAt(LocalDateTime.now());
            messageMapper.updateById(message);
            log.debug("标记消息为已读, ID: {}", messageId);
        }
    }

    @Override
    @Transactional
    public void batchMarkAsRead(List<Long> messageIds, Long userId) {
        messageMapper.batchMarkAsRead(messageIds, userId);
        log.info("批量标记消息为已读, 用户: {}, 消息数量: {}", userId, messageIds.size());
    }

    @Override
    @Transactional
    public void markConversationAsRead(String conversationId, Long userId) {
        messageMapper.markConversationAsRead(conversationId, userId);
        log.info("标记会话消息为已读, 会话: {}, 用户: {}", conversationId, userId);
    }

    @Override
    @Transactional
    public void deleteMessage(Long messageId, Long userId) {
        Message message = getMessageById(messageId);
        
        // 检查权限：只有接收者可以删除消息
        if (!message.getToUserId().equals(userId)) {
            throw new BusinessException(ResultCode.FORBIDDEN);
        }

        message.setStatus(Message.Status.DELETED.name());
        messageMapper.updateById(message);
        log.info("删除消息成功, ID: {}", messageId);
    }

    @Override
    public Message getMessageById(Long id) {
        Message message = messageMapper.selectById(id);
        if (message == null) {
            throw new BusinessException(ResultCode.NOT_FOUND);
        }
        return message;
    }

    @Override
    public IPage<Message> getMessagePage(Page<Message> page, Long userId, String conversationId, String type, String status) {
        return messageMapper.selectMessagePageWithUser(page, userId, conversationId, type, status);
    }

    @Override
    public List<Message> getConversationMessages(String conversationId, Integer limit) {
        if (limit == null || limit <= 0) {
            limit = 50;
        }
        return messageMapper.selectByConversationId(conversationId, limit);
    }

    @Override
    public List<Message> getUnreadMessages(Long userId) {
        return messageMapper.selectUnreadMessages(userId);
    }

    @Override
    public Integer countUnreadMessages(Long userId) {
        return messageMapper.countUnreadMessages(userId);
    }

    @Override
    public Integer countUnreadByConversation(String conversationId, Long userId) {
        return messageMapper.countUnreadByConversation(conversationId, userId);
    }

    @Override
    public List<Message> getSystemMessages(Long userId, Integer limit) {
        if (limit == null || limit <= 0) {
            limit = 20;
        }
        return messageMapper.selectSystemMessages(userId, limit);
    }

    @Override
    public List<Message> getRecentChatUsers(Long userId, Integer limit) {
        if (limit == null || limit <= 0) {
            limit = 10;
        }
        return messageMapper.selectRecentChatUsers(userId, limit);
    }

    @Override
    public void handleUserOnline(Long userId) {
        // 处理用户上线逻辑
        log.info("用户上线: {}", userId);
        // 可以在这里推送离线消息等
    }

    @Override
    public void handleUserOffline(Long userId) {
        // 处理用户下线逻辑
        log.info("用户下线: {}", userId);
    }

    @Override
    @Transactional
    public void cleanExpiredMessages(Integer days) {
        if (days == null || days <= 0) {
            days = 30; // 默认清理30天前的消息
        }
        LocalDateTime beforeDate = LocalDateTime.now().minusDays(days);
        messageMapper.deleteExpiredMessages(beforeDate);
        log.info("清理{}天前的过期消息成功", days);
    }

    /**
     * 获取或创建会话
     */
    private String getOrCreateConversation(Long user1Id, Long user2Id) {
        // 查找现有的私聊会话
        Conversation conversation = conversationMapper.selectPrivateConversation(user1Id, user2Id);
        
        if (conversation == null) {
            // 创建新会话
            String conversationId = IdUtil.simpleUUID();
            conversation = new Conversation();
            conversation.setId(conversationId);
            conversation.setType(Conversation.Type.PRIVATE.name());
            
            // 设置参与者列表
            List<Long> participants = Arrays.asList(user1Id, user2Id);
            conversation.setParticipants(JSONUtil.toJsonStr(participants));
            
            conversationMapper.insert(conversation);
            log.info("创建新会话, ID: {}, 参与者: {}", conversationId, participants);
            
            return conversationId;
        }
        
        return conversation.getId();
    }
}
